part of '../index.dart';

enum PannelType { gift, record, none, keyboard, emoji }

class PannelController extends ChangeNotifier {
  PannelType pannelType = PannelType.none;
  bool showPannel = false;

  void toggle(PannelType type, {BuildContext? context}) {
    if (showPannel && pannelType == type) {
      hide();
      return;
    }
    if (type == PannelType.keyboard) {
      if (context != null) context.read<ChatProvider>().focus.requestFocus();
      showPannel = true;
      pannelType = type;
      notifyListeners();
      return;
    }
    if (type != PannelType.none) {
      Tools.unfocus();
      showPannel = true;
      pannelType = type;
      notifyListeners();
    }
  }

  void hide() {
    Tools.unfocus();
    showPannel = false;
    pannelType = PannelType.none;
    notifyListeners();
  }
}

class OperateBar extends StatefulWidget {
  const OperateBar({super.key, required this.controller});
  final PannelController controller;

  @override
  State<OperateBar> createState() => _OperateBarState();
}

class _OperateBarState extends State<OperateBar> with WidgetsBindingObserver {
  double pannelHeight = 320;
  late PannelController controller = widget.controller;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    final cacheHeight = double.tryParse(CacheUtil.get(Constants.kKBH));
    if ((cacheHeight ?? 0) >= 200) pannelHeight = cacheHeight ?? 320;
  }

  @override
  void didChangeMetrics() {
    Debouncer.run('_c_k_h', const Duration(milliseconds: 100), () {
      if (mounted) {
        final height = MediaQuery.of(context).viewInsets.bottom;
        if (height <= 0) return;
        CacheUtil.set(Constants.kKBH, height.toString());
        if (pannelHeight != height) pannelHeight = height;
      }
    });
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  void _onGallery() async {
    final result = await AssetPicker.pickAssets(
      context,
      pickerConfig: const AssetPickerConfig(
        maxAssets: 6,
      ),
    );
    if (result == null || result.isEmpty) return;
    if (result.length == 1) {
      _handleSend(result.first);
    } else {
      Future.wait(result.map(_handleSend));
    }
  }

  void _onCamera() async {
    final entity = await CameraPicker.pickFromCamera(
      context,
      pickerConfig: const CameraPickerConfig(
        enableRecording: true,
        resolutionPreset: ResolutionPreset.max,
      ),
    );
    if (entity == null) return;
    _handleSend(entity);
  }

  Future<void> _handleSend(AssetEntity entity) async {
    final mimeType = entity.mimeType ?? '';
    final type = entity.type;

    if (mimeType.contains('video') ||
        mimeType.contains('mp4') ||
        type == AssetType.video) {
      if (mounted) context.read<ChatProvider>().sendVideoMessage(entity);
      return;
    }
    if (mimeType.contains('image') ||
        mimeType.contains('jpeg') ||
        type == AssetType.image) {
      if (mounted) context.read<ChatProvider>().sendImageMessage(entity);
      return;
    }
  }

  void _onCall() {
    final provier = context.read<ChatProvider>();
    final cid = provier.conversation?.id;
    if (cid == null) return;
    final imId = UserManager.instance.currentUser?.imId;
    Get.to(() => CallPage(from: imId, to: cid, type: CallType.call));
  }

  @override
  Widget build(BuildContext context) {
    final provider = context.watch<ChatProvider>();
    return ListenableBuilder(
      listenable: controller,
      builder: (context, cihld) {
        return Container(
          padding: const EdgeInsets.only(left: 10, right: 10, top: 10),
          decoration: BoxDecoration(
            color: Colors.white,
            boxShadow: [
              BoxShadow(
                color: const Color(0xFF787878).withOpacity(0.1),
                offset: const Offset(0, 0),
                blurRadius: 9,
              ),
            ],
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  BuildTextInput(
                    controller: provider.input,
                    focusNode: provider.focus,
                    onSendText: context.read<ChatProvider>().sendTextMessage,
                    onTapGift: () => controller.toggle(PannelType.gift),
                    onTapEmoji: () => controller.toggle(PannelType.emoji),
                    onTap: () {
                      controller.toggle(PannelType.keyboard, context: context);
                    },
                  ),
                  if (controller.pannelType != PannelType.gift)
                    Padding(
                      padding: EdgeInsets.only(
                        bottom: controller.showPannel ? 0 : 34,
                      ),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: [
                          _BarOption(
                            icon: Images.icChatRecord,
                            onTap: () {
                              Tools.unfocus();
                              controller.toggle(PannelType.record);
                            },
                          ),
                          _BarOption(
                              icon: Images.icChatGaller, onTap: _onGallery),
                          _BarOption(
                              icon: Images.icChatCamera, onTap: _onCamera),
                          _BarOption(icon: Images.icChatCall, onTap: _onCall),
                        ],
                      ),
                    ),
                ],
              ),
              Builder(
                builder: (context) {
                  Widget child = const SizedBox();
                  if (controller.pannelType == PannelType.record) {
                    child = const VoiceRecording();
                  }
                  if (controller.pannelType == PannelType.gift) {
                    child = const MessageGift();
                  }
                  if (controller.pannelType == PannelType.emoji) {
                    child = MessageEmoji(
                      onTap: (emoji) => provider.input.text += emoji,
                    );
                  }
                  return _AdditionalArea(
                    show: controller.showPannel,
                    height: pannelHeight,
                    child: child,
                  );
                },
              ),
            ],
          ),
        );
      },
    );
  }
}

class _AdditionalArea extends StatelessWidget {
  final bool show;
  final Widget? child;
  final double height;

  const _AdditionalArea({required this.height, this.show = false, this.child});

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        SizedBox(height: show ? height : 0),
        Positioned.fill(
          child: AnimatedContainer(
            margin: show ? const EdgeInsets.only(top: 10) : null,
            duration: const Duration(milliseconds: 200),
            height: show ? 300 : 0,
            child: AnimatedOpacity(
              duration: const Duration(milliseconds: 200),
              opacity: show ? 1 : 0,
              child: child,
            ),
          ),
        ),
      ],
    );
  }
}

class _BarOption extends StatelessWidget {
  const _BarOption({required this.icon, this.onTap});
  final String icon;
  final VoidCallback? onTap;
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      behavior: HitTestBehavior.opaque,
      child: Padding(
        padding: const EdgeInsets.all(2),
        child: Image.asset(icon, width: 32, height: 32),
      ),
    );
  }
}
